package com.mvc.finance.service;

import java.util.Date;
import java.util.List;

import org.hibernate.Query;
import org.hibernate.Session;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.mvc.base.service.BaseCompanyManager;
import com.mvc.base.service.UserCompanyManager;
import com.mvc.finance.model.ExpenseApply;
import com.mvc.finance.model.ExpenseApplyItem;
import com.mvc.framework.dao.HibernateIdUtils;
import com.mvc.framework.model.Auditable;
import com.mvc.framework.model.CommonAuditableEntity;
import com.mvc.framework.util.DateUtils;
import com.mvc.framework.util.FrameworkContextUtils;

@Service
public class ExpenseApplyManager extends BaseCompanyManager<ExpenseApply, Integer> {

	@Autowired
	private ExpenseApplyItemManager	expenseApplyItemManager;

	@Autowired
	private UserCompanyManager	    userCompanyManager;

	@Autowired
	private FinancePrivilegeManager	financePrivilegeManager;

	public ExpenseApply getObject(Integer objectId) {
		ExpenseApply order = super.getByObjectId(objectId);
		if (order != null) {
			order.setExpenseApplyItems(expenseApplyItemManager.getExpenseApplyItemsByExpenseApplyId(order.getObjectId()));
			order.setCompany(companyManager.getByObjectId(order.getCompanyId()));
		}
		return order;
	}

	public void save(ExpenseApply entity) {
		entity.setTotal(getTotal(entity.getObjectId()));
		if (null == entity.getId()) {
			Integer oldOrderId = entity.getObjectId();
			entity.setObjectId(HibernateIdUtils.getUnCacheCustomizeId(getHibernateTemplate().getSessionFactory(), "expenseApplyNo"));
			expenseApplyItemManager.updateExpenseApplyItemId(oldOrderId, entity.getObjectId());
		}
		super.save(entity);
	}

	protected Double getTotal(Integer expenseApplyId) {
		Double total = 0D;
		if (expenseApplyId != null) {
			List<ExpenseApplyItem> orderItems = expenseApplyItemManager.getExpenseApplyItemsByExpenseApplyId(expenseApplyId);
			for (ExpenseApplyItem orderItem : orderItems) {
				total += (orderItem.getAmount());
			}
		}
		return total;
	}

	public Double getTotalNeedPay() {
		String companyId = userCompanyManager.getCompanyIdsByUserId(FrameworkContextUtils.getCurrentUserId());
		String sql = "select sum(total) from " + ExpenseApply.class.getName() + " where recStatus=? and status = ?";
		if (companyId == null) {
		} else if (companyId.length() > 0) {
			sql += " and companyId in(" + companyId + ")";
		} else {
			return 0D;
		}
		return searchObjectBySql(Double.class, sql, new Object[] { CommonAuditableEntity.REC_STATUS_VALID, ExpenseApply.STATUS_APPROVAED });
	}

	public Double getTotalPayed() {
		String sql = "select sum(total) from " + ExpenseApply.class.getName() + " where recStatus=? and status =?";
		String companyId = userCompanyManager.getCompanyIdsByUserId(FrameworkContextUtils.getCurrentUserId());
		if (companyId == null) {
		} else if (companyId.length() > 0) {
			sql += " and companyId in(" + companyId + ")";
		} else {
			return 0D;
		}
		return searchObjectBySql(Double.class, sql, new Object[] { CommonAuditableEntity.REC_STATUS_VALID, ExpenseApply.STATUS_PAYED });
	}

	public Double getTotalPayedByMonth(Date month) {
		Date monthBegin = DateUtils.getBeginDateOfTheMonth(month);
		Date monthEnd = DateUtils.getLastDateOfTheMonth(month);
		String sql = "select sum(total) from " + ExpenseApply.class.getName()
		        + " where recStatus=? and status =? and payDate>=? and payDate <= ?";
		String companyId = userCompanyManager.getCompanyIdsByUserId(FrameworkContextUtils.getCurrentUserId());
		if (companyId == null) {
		} else if (companyId.length() > 0) {
			sql += " and companyId in(" + companyId + ")";
		} else {
			return 0D;
		}
		return (Double) searchObjectBySql(Double.class, sql, new Object[] { CommonAuditableEntity.REC_STATUS_VALID,
		        ExpenseApply.STATUS_PAYED, monthBegin, monthEnd });
	}

	public List<Object> getCount(Integer companyId, Date beginDate, Date endDate) {
		Session session = getHibernateTemplate().getSessionFactory().openSession();
		Query query = session.createQuery("select count(*) from " + ExpenseApply.class.getName()
		        + " where recStatus = ? and status>= ? and companyId=? and payDate >= ? and payDate <= ?");
		query.setParameter(0, Auditable.REC_STATUS_VALID).setParameter(1, ExpenseApply.STATUS_PAYED).setParameter(2, companyId)
		        .setParameter(3, beginDate).setParameter(4, endDate);
		List<Object> result = query.list();
		session.close();
		return result;
	}

	public Long getNeedAuditCount() {
		Session session = getHibernateTemplate().getSessionFactory().openSession();
		Query query = session.createQuery("select count(*) from " + ExpenseApply.class.getName() + " where recStatus = ? and status= ?");
		query.setParameter(0, Auditable.REC_STATUS_VALID).setParameter(1, ExpenseApply.STATUS_COMMIT);
		List<Object> result = query.list();
		session.close();
		return (Long) result.get(0);
	}

	public List<Object[]> summary(Integer companyId, Date beginDate, Date endDate) {
		Session session = getHibernateTemplate().getSessionFactory().openSession();
		Query query = session.createQuery("select count(*),sum(total) from " + ExpenseApply.class.getName()
		        + " where recStatus = ? and status= ? and companyId=? and payDate >= ? and payDate <= ?");
		query.setParameter(0, Auditable.REC_STATUS_VALID).setParameter(1, ExpenseApply.STATUS_PAYED).setParameter(2, companyId)
		        .setParameter(3, beginDate).setParameter(4, endDate);
		return query.list();
	}
}
